/***************************************************************************
 *   Copyright (C) 2008 - 2009 by Pavel Andreev                            *
 *   Mail: apavelm on gmail point com (apavelm@gmail.com)                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "dircompare.h"
#include <QtAlgorithms>

CompareTreeItem::CompareTreeItem(const QList<QVariant> &data, CompareTreeItem *parent)
{
	parentItem = parent;
	itemData = data;
}

CompareTreeItem::~CompareTreeItem()
{
	qDeleteAll(childItems);
}

void CompareTreeItem::appendChild(CompareTreeItem *item)
{
	childItems.append(item);
}

CompareTreeItem * CompareTreeItem::child(int row)
{
	return childItems.value(row);
}

int CompareTreeItem::childCount() const
{
	return childItems.count();
}

int CompareTreeItem::columnCount() const
{
	return itemData.count();
}

QVariant CompareTreeItem::data(int column) const
{
	return itemData.value(column);
}

CompareTreeItem * CompareTreeItem::parent()
{
	return parentItem;
}

int CompareTreeItem::row() const
{
	if (parentItem)
		return parentItem->childItems.indexOf(const_cast<CompareTreeItem*>(this));

	return 0;
}
 
///////// DirCompareModel

DirCompareModel::DirCompareModel( QObject * parent,
		const QString& left,
		const QString& right,
		const QString& filter,
		bool isRecursive,
		bool onlyDifferences) : QAbstractListModel(parent), 
								m_left(left), 
								m_right(right), 
								m_filter(filter), 
								m_recursive(isRecursive), 
								m_onlyDifferences(onlyDifferences)
{
	QList<QVariant> rootData;
	rootData	<< QObject::tr("Filename") 
				<< QObject::tr("Compare result")
				<< QObject::tr("Date left")
				<< QObject::tr("Date right")
				<< QObject::tr("File extension");
	rootItem = new CompareTreeItem(rootData);
	
        FolderCmp folderCompare;
        folderCompare.addDirectory(QString("/home/irq/test/a1"));
        folderCompare.addDirectory(QString("/home/irq/test/a2"));
        FolderCmpResult r = folderCompare.compare();
        QStringList strFileList;
        for (FolderCmpResult::iterator it = r.begin(); it != r.end(); ++it)
        {
           strFileList.append( it->fileinfo.fileName() + QString("\t%1\t%2").arg(it->status[0]).arg(it->status[1]) );
        }
        setupModelData(strFileList, rootItem);
}

DirCompareModel::~DirCompareModel()
{
	delete rootItem;
}

int DirCompareModel::columnCount(const QModelIndex &parent) const
{
	if (parent.isValid())
		return static_cast<CompareTreeItem*>(parent.internalPointer())->columnCount();
	else
		return rootItem->columnCount();
 }

QVariant DirCompareModel::data(const QModelIndex &index, int role) const
{
	if (!index.isValid())
		return QVariant();

	if (role != Qt::DisplayRole)
		return QVariant();

	CompareTreeItem * item = static_cast<CompareTreeItem*>(index.internalPointer());

	return item->data(index.column());
}

Qt::ItemFlags DirCompareModel::flags(const QModelIndex &index) const
{
	if (!index.isValid()) 
		return Qt::NoItemFlags;

	return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant DirCompareModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
		return rootItem->data(section);

	return QVariant();
}

QModelIndex DirCompareModel::index(int row, int column, const QModelIndex &parent) const
{
	if (!hasIndex(row, column, parent))
		return QModelIndex();

	CompareTreeItem *parentItem;

	if (!parent.isValid())
		parentItem = rootItem;
	else
		parentItem = static_cast<CompareTreeItem*>(parent.internalPointer());

	CompareTreeItem * childItem = parentItem->child(row);
	if (childItem)
		return createIndex(row, column, childItem);
	else
		return QModelIndex();
}

QModelIndex DirCompareModel::parent(const QModelIndex &index) const
{
	if (!index.isValid())
		return QModelIndex();

	CompareTreeItem * childItem = static_cast<CompareTreeItem*>(index.internalPointer());
	CompareTreeItem * parentItem = childItem->parent();

	if (parentItem == rootItem)
		return QModelIndex();

	return createIndex(parentItem->row(), 0, parentItem);
}

int DirCompareModel::rowCount(const QModelIndex &parent) const
{
	CompareTreeItem * parentItem;
	if (parent.column() > 0)
		return 0;

	if (!parent.isValid())
		parentItem = rootItem;
	else
		parentItem = static_cast<CompareTreeItem*>(parent.internalPointer());

	return parentItem->childCount();
}

void DirCompareModel::setupModelData(const QStringList &lines, CompareTreeItem * parent)
{
	QList<CompareTreeItem*> parents;
	QList<int> indentations;
	parents << parent;
	indentations << 0;

	int number = 0;

	while (number < lines.count())
	{
		int position = 0;
		while (position < lines[number].length())
		{
			if (lines[number].mid(position, 1) != " ")
				break;
			position++;
		}

		QString lineData = lines[number].mid(position).trimmed();

		if (!lineData.isEmpty()) 
		{
			// Read the column data from the rest of the line.
			QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);
			QList<QVariant> columnData;
			for (int column = 0; column < columnStrings.count(); ++column)
			columnData << columnStrings[column];

			if (position > indentations.last()) 
			{
				// The last child of the current parent is now the new parent
				// unless the current parent has no children.

				if (parents.last()->childCount() > 0) 
				{
					parents << parents.last()->child(parents.last()->childCount()-1);
					indentations << position;
				}
			} 
			else 
				{
					while (position < indentations.last() && parents.count() > 0) {
						parents.pop_back();
						indentations.pop_back();
					}
				}

			// Append a new item to the current parent's list of children.
			parents.last()->appendChild(new CompareTreeItem(columnData, parents.last()));
		}

		number++;
	}
}

/* @class DirCompareCtrl
* Control for compare directories.
*/
DirCompareCtrl::DirCompareCtrl(	QWidget * parent, 
								const QString& strLeft, 
								const QString& strRight,
								const QString& strFilter /*= QString::null()*/,
								bool showOnlyDifferences /*= true*/,
								bool isRecursive /*= true*/ ) : QWidget(parent)
{
	setupUi(this);
	
	lblLeft->setText(strLeft);
	lblRight->setText(strRight);
	QAbstractItemModel *model = new DirCompareModel(this, strLeft, strRight, strFilter, isRecursive, showOnlyDifferences);
	listDir->setModel(model);
}
